using SharpDX;
using System.Collections.Generic;
using System.IO;

namespace WorldRacing2.Scenario.WR2TerrainLoader
{
    public class VertexBlock
    {
        #region Public Fields

        public List<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured> engineVertices;

        #endregion Public Fields

        #region Internal Fields

        internal List<MyOwnVertex.Wr2Data> wr2Data;

        #endregion Internal Fields

        #region Internal Constructors

        internal VertexBlock(BinaryReader br, int numberOfVertices)
        {
            //this.wr2Vertices = new WR2Vertex[numberOfVertices];
            this.engineVertices = new List<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured>(ushort.MaxValue);
            this.wr2Data = new List<MyOwnVertex.Wr2Data>(ushort.MaxValue);

            //long startPosition = br.BaseStream.Position;
            //br.BaseStream.Position = startPosition;

            for (int i = 0; i < numberOfVertices; i++)
            {
                //wr2Vertices[i] = new WR2Vertex(br);

                Vector3 position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());

                int nX = (int)br.ReadByte() - 128;
                int nY = (int)br.ReadByte() - 128;
                int nZ = (int)br.ReadByte() - 128;
                br.BaseStream.Position += 1;
                Vector3 normal = Vector3.Normalize(new Vector3(nX, nY, nZ));

                Vector2 textureCoordinates = new Vector2(br.ReadSingle(), br.ReadSingle());

                byte[] blend = br.ReadBytes(4); // BlendR,BlendG,BlendB,Shadow

                //Color4 blendColor = new Color4(blend[3] / 255.0f, blend[0] / 255.0f, blend[1] / 255.0f, blend[2] / 255.0f); // Vor der SharpDx Zeit
                Color4 blendColor = new Color4(blend[0] / 255.0f, blend[1] / 255.0f, blend[2] / 255.0f, blend[3] / 255.0f); // SharpDX11

                blend = br.ReadBytes(4); // B,G,R,A
                //Color4 diffuseColor = new Color4(blend[3] / 255.0f, blend[2] / 255.0f, blend[1] / 255.0f, blend[0] / 255.0f);
                Color4 diffuseColor = new Color4(blend[2] / 255.0f, blend[1] / 255.0f, blend[0] / 255.0f, blend[3] / 255.0f);// SharpDX11

                this.engineVertices.Add(new Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured()
                {
                    Position = position,
                    Normal = normal,
                    UV = new Vector2(textureCoordinates.X, textureCoordinates.Y)
                });
                this.wr2Data.Add(new MyOwnVertex.Wr2Data()
                {
                    UV = new Vector2(textureCoordinates.X, textureCoordinates.Y),
                    UV2 = new Vector2(textureCoordinates.X, textureCoordinates.Y),
                    DiffuseColor = diffuseColor,
                    VertexColor = blendColor
                });

                //engineVertices.Add(new MyOwnVertex.MyPositionNormalTextured(
                //    position,
                //    normal,
                //    textureCoordinates.X, textureCoordinates.Y,
                //    textureCoordinates.X, textureCoordinates.Y,
                //    new Color4(0.1f, 0.2f, 0.3f, 0.4f), // DifuseColor
                //    new Color4(0.5f, 0.6f, 0.7f, 0.8f))); // VertexColor/BlendColor
            }
        }

        internal VertexBlock()
        {
            this.engineVertices = new List<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured>(ushort.MaxValue);
            this.wr2Data = new List<MyOwnVertex.Wr2Data>(ushort.MaxValue);
        }

        #endregion Internal Constructors

        #region Internal Methods

        internal void Dispose()
        {
            this.engineVertices.Clear();
            this.engineVertices = null;
        }

        internal void Reset()
        {
            this.engineVertices.Clear();
        }

        internal void Save(BinaryWriter bw)
        {
            //for (int i = 0; i < this.wr2Vertices.Length; i++)
            //{
            //    this.wr2Vertices[i].Save(bw);
            //}
            // foreach (var vertex in this.engineVertices)
            for (int i = 0; i < this.engineVertices.Count; i++)

            {
                Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured vertex = this.engineVertices[i];
                MyOwnVertex.Wr2Data vertexWr2 = this.wr2Data[i];

                //Vector3 position = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                bw.Write(vertex.Position.X);
                bw.Write(vertex.Position.Y);
                bw.Write(vertex.Position.Z);

                byte[] byteArray = new byte[4];

                byteArray[0] = (byte)(vertex.Normal.X * 128 + 127);
                byteArray[1] = (byte)(vertex.Normal.Y * 128 + 127);
                byteArray[2] = (byte)(vertex.Normal.Z * 128 + 127);
                byteArray[3] = 0x00;
                // Write Normal
                bw.Write(byteArray);

                // Write texture Coordinates.
                bw.Write(vertexWr2.Tu);
                bw.Write(vertexWr2.Tv);

                // Write the vertex Color.
                // BlendR,BlendG,BlendB,Shadow
                byteArray[0] = (byte)(vertexWr2.VertexColor.Red * 255.0f);
                byteArray[1] = (byte)(vertexWr2.VertexColor.Green * 255.0f);
                byteArray[2] = (byte)(vertexWr2.VertexColor.Blue * 255.0f);
                byteArray[3] = (byte)(vertexWr2.VertexColor.Alpha * 255.0f);
                bw.Write(byteArray);

                // Write the diffuse color
                // B,G,R,A
                byteArray[0] = (byte)(vertexWr2.DiffuseColor.Blue * 255.0f);
                byteArray[1] = (byte)(vertexWr2.DiffuseColor.Green * 255.0f);
                byteArray[2] = (byte)(vertexWr2.DiffuseColor.Red * 255.0f);
                byteArray[3] = (byte)(vertexWr2.DiffuseColor.Alpha * 255.0f);
                bw.Write(byteArray);
            }
        }

        #endregion Internal Methods
    }
}